home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / dflat_r_.arc / MESSAGE.C < prev    next >
Text File  |  1991-10-02  |  17KB  |  551 lines

  1. /* --------- message.c ---------- */
  2.  
  3. #include <stdio.h>
  4. #include <dos.h>
  5. #include <conio.h>
  6. #include <string.h>
  7. #include <time.h>
  8. #include "dflat.h"
  9.  
  10. static int px = -1, py = -1;
  11. static int pmx = -1, pmy = -1;
  12. static int mx, my;
  13.  
  14. static int CriticalError;
  15.  
  16. /* ---------- event queue ---------- */
  17. static struct events    {
  18.     MESSAGE event;
  19.     int mx;
  20.     int my;
  21. } EventQueue[MAXMESSAGES];
  22.  
  23. /* ---------- message queue --------- */
  24. static struct msgs {
  25.     WINDOW wnd;
  26.     MESSAGE msg;
  27.     PARAM p1;
  28.     PARAM p2;
  29. } MsgQueue[MAXMESSAGES];
  30.  
  31. static int EventQueueOnCtr;
  32. static int EventQueueOffCtr;
  33. static int EventQueueCtr;
  34.  
  35. static int MsgQueueOnCtr;
  36. static int MsgQueueOffCtr;
  37. static int MsgQueueCtr;
  38.  
  39. static int lagdelay = FIRSTDELAY;
  40.  
  41. static void (interrupt far *oldtimer)(void);
  42. static void (interrupt far *oldkeyboard)(void);
  43.  
  44. static int keyportvalue;    /* for watching for key release */
  45.  
  46. WINDOW CaptureMouse;
  47. WINDOW CaptureKeyboard;
  48. static int NoChildCaptureMouse;
  49. static int NoChildCaptureKeyboard;
  50.  
  51. static int doubletimer = -1;
  52. static int delaytimer  = -1;
  53. #ifdef INCLUDE_CLOCK
  54. static int clocktimer  = -1;
  55. #endif
  56.  
  57. static WINDOW Cwnd;
  58.  
  59. static void interrupt far newkeyboard(void)
  60. {
  61.     keyportvalue = inp(KEYBOARDPORT);
  62.     oldkeyboard();
  63. }
  64.  
  65. /* ------- timer interrupt service routine ------- */
  66. static void interrupt far newtimer(void)
  67. {
  68.     if (timer_running(doubletimer))
  69.         countdown(doubletimer);
  70.     if (timer_running(delaytimer))
  71.         countdown(delaytimer);
  72. #ifdef INCLUDE_CLOCK
  73.     if (timer_running(clocktimer))
  74.         countdown(clocktimer);
  75. #endif
  76.     oldtimer();
  77. }
  78.  
  79. static char ermsg[] = "Error accessing drive x";
  80.  
  81. /* -------- test for critical errors --------- */
  82. int TestCriticalError(void)
  83. {
  84.     int rtn = 0;
  85.     if (CriticalError)    {
  86.         rtn = 1;
  87.         CriticalError = FALSE;
  88.         if (TestErrorMessage(ermsg) == FALSE)
  89.             rtn = 2;
  90.     }
  91.     return rtn;
  92. }
  93.  
  94. /* ------ critical error interrupt service routine ------ */
  95. static void interrupt far newcrit(IREGS ir)
  96. {
  97.     if (!(ir.ax & 0x8000))     {
  98.         ermsg[sizeof(ermsg) - 2] = (ir.ax & 0xff) + 'A';
  99.         CriticalError = TRUE;
  100.     }
  101.     ir.ax = 0;
  102. }
  103.  
  104. /* ------------ initialize the message system --------- */
  105. void init_messages(void)
  106. {
  107.     resetmouse();
  108.     initvideo();
  109.     set_mousetravel(0, SCREENWIDTH-1, 0, SCREENHEIGHT-1);
  110.     savecursor();
  111.     hidecursor();
  112.     px = py = -1;
  113.     pmx = pmy = -1;
  114.     mx = my = 0;
  115.     CaptureMouse = CaptureKeyboard = NULLWND;
  116.     NoChildCaptureMouse = FALSE;
  117.     NoChildCaptureKeyboard = FALSE;
  118.     MsgQueueOnCtr = MsgQueueOffCtr = MsgQueueCtr = 0;
  119.     EventQueueOnCtr = EventQueueOffCtr = EventQueueCtr = 0;
  120.     if (oldtimer == NULL)    {
  121.         oldtimer = getvect(TIMER);
  122.         setvect(TIMER, newtimer);
  123.     }
  124.     if (oldkeyboard == NULL)    {
  125.         oldkeyboard = getvect(KEYBOARDVECT);
  126.         setvect(KEYBOARDVECT, newkeyboard);
  127.     }
  128.     setvect(CRIT, newcrit);
  129.     PostMessage(NULLWND,START,0,0);
  130.     lagdelay = FIRSTDELAY;
  131. }
  132.  
  133. /* ----- post an event and parameters to event queue ---- */
  134. static void PostEvent(MESSAGE event, int p1, int p2)
  135. {
  136.     if (EventQueueCtr != MAXMESSAGES)    {
  137.         EventQueue[EventQueueOnCtr].event = event;
  138.         EventQueue[EventQueueOnCtr].mx = p1;
  139.         EventQueue[EventQueueOnCtr].my = p2;
  140.         if (++EventQueueOnCtr == MAXMESSAGES)
  141.             EventQueueOnCtr = 0;
  142.         EventQueueCtr++;
  143.     }
  144. }
  145.  
  146. /* ------ collect mouse, clock, and keyboard events ----- */
  147. static void near collect_events(void)
  148. {
  149.     static int ShiftKeys = 0;
  150.     int sk;
  151. #ifdef INCLUDE_CLOCK
  152.     struct tm *now;
  153.     static int flipflop = FALSE;
  154.     static char timestr[9];
  155.     int hr;
  156.  
  157.     /* -------- test for a clock event (one/second) ------- */
  158.     if (timed_out(clocktimer))    {
  159.         /* ----- get the current time ----- */
  160.         time_t t = time(NULL);
  161.         now = localtime(&t);
  162.         hr = now->tm_hour > 12 ?
  163.              now->tm_hour - 12 :
  164.              now->tm_hour;
  165.         if (hr == 0)
  166.             hr = 12;
  167.         sprintf(timestr, "%2d:%02d", hr, now->tm_min);
  168.         strcpy(timestr+5, now->tm_hour > 11 ? "pm " : "am ");
  169.         /* ------- blink the : at one-second intervals ----- */
  170.         if (flipflop)
  171.             *(timestr+2) = ' ';
  172.         flipflop ^= TRUE;
  173.         /* -------- reset the timer -------- */
  174.         set_timer(clocktimer, 1);
  175.         /* -------- post the clock event -------- */
  176.         PostEvent(CLOCKTICK, FP_SEG(timestr), FP_OFF(timestr));
  177.     }
  178. #endif
  179.  
  180.     /* --------- keyboard events ---------- */
  181.     if ((sk = getshift()) != ShiftKeys)    {
  182.         ShiftKeys = sk;
  183.         /* ---- the shift status changed ---- */
  184.         PostEvent(SHIFT_CHANGED, sk, 0);
  185.     }
  186.  
  187.     /* ---- build keyboard events for key combinations that
  188.         BIOS doesn't report --------- */
  189.     if (sk & ALTKEY)
  190.         if (inp(0x60) == 14)    {
  191.             waitforkeyboard();
  192.             PostEvent(KEYBOARD, ALT_BS, sk);
  193.         }
  194.     if (sk & CTRLKEY)
  195.         if (inp(0x60) == 82)    {
  196.             while (!(inp(0x60) & 0x80))
  197.             waitforkeyboard();
  198.             PostEvent(KEYBOARD, CTRL_INS, sk);
  199.         }
  200.  
  201.     /* ----------- test for keystroke ------- */
  202.     if (keyhit())    {
  203.         static int cvt[] = {SHIFT_INS,END,DN,PGDN,BS,'5',
  204.                         FWD,HOME,UP,PGUP};
  205.         int c = getkey();
  206.  
  207.         /* -------- convert numeric pad keys ------- */
  208.         if (sk & (LEFTSHIFT | RIGHTSHIFT))    {
  209.             if (c >= '0' && c <= '9')
  210.                 c = cvt[c-'0'];
  211.             else if (c == '.' || c == DEL)
  212.                 c = SHIFT_DEL;
  213.             else if (c == INS)
  214.                 c = SHIFT_INS;
  215.         }
  216.         if (c != '\r' && (c < ' ' || c > 127))
  217.             clearBIOSbuffer();
  218.         /* ------ post the keyboard event ------ */
  219.         PostEvent(KEYBOARD, c, sk);
  220.     }
  221.  
  222.     /* ------------ test for mouse events --------- */
  223.     if (button_releases())    {
  224.         /* ------- the button was released -------- */
  225.         doubletimer = DOUBLETICKS;
  226.         PostEvent(BUTTON_RELEASED, mx, my);
  227.         disable_timer(delaytimer);
  228.     }
  229.     get_mouseposition(&mx, &my);
  230.     if (mx != px || my != py)  {
  231.         px = mx;
  232.         py = my;
  233.         PostEvent(MOUSE_MOVED, mx, my);
  234.     }
  235.     if (rightbutton())
  236.         PostEvent(RIGHT_BUTTON, mx, my);
  237.     if (leftbutton())    {
  238.         if (mx == pmx && my == pmy)    {
  239.             /* ---- same position as last left button ---- */
  240.             if (timer_running(doubletimer))    {
  241.                 /* -- second click before double timeout -- */
  242.                 disable_timer(doubletimer);
  243.                 PostEvent(DOUBLE_CLICK, mx, my);
  244.             }
  245.             else if (!timer_running(delaytimer))    {
  246.                 /* ---- button held down a while ---- */
  247.                 delaytimer = lagdelay;
  248.                 lagdelay = DELAYTICKS;
  249.                 /* ---- post a typematic-like button ---- */
  250.                 PostEvent(LEFT_BUTTON, mx, my);
  251.             }
  252.         }
  253.         else    {
  254.             /* --------- new button press ------- */
  255.             disable_timer(doubletimer);
  256.             delaytimer = FIRSTDELAY;
  257.             lagdelay = DELAYTICKS;
  258.             PostEvent(LEFT_BUTTON, mx, my);
  259.             pmx = mx;
  260.             pmy = my;
  261.         }
  262.     }
  263.     else
  264.         lagdelay = FIRSTDELAY;
  265. }
  266.  
  267. /* ----- post a message and parameters to msg queue ---- */
  268. void PostMessage(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  269. {
  270.     if (MsgQueueCtr != MAXMESSAGES)    {
  271.         MsgQueue[MsgQueueOnCtr].wnd = wnd;
  272.         MsgQueue[MsgQueueOnCtr].msg = msg;
  273.         MsgQueue[MsgQueueOnCtr].p1 = p1;
  274.         MsgQueue[MsgQueueOnCtr].p2 = p2;
  275.         if (++MsgQueueOnCtr == MAXMESSAGES)
  276.             MsgQueueOnCtr = 0;
  277.         MsgQueueCtr++;
  278.     }
  279. }
  280.  
  281. /* --------- send a message to a window ----------- */
  282. int SendMessage(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  283. {
  284.     int rtn = TRUE, x, y;
  285.  
  286. #ifdef INCLUDE_LOGGING
  287.     LogMessages(wnd, msg, p1, p2);
  288. #endif
  289.     if (wnd != NULLWND)
  290.         switch (msg)    {
  291.             case PAINT:
  292.             case BORDER:
  293.                 /* ------- don't send these messages unless the
  294.                     window is visible -------- */
  295.                 if (isVisible(wnd))
  296.                     rtn = (*wnd->wndproc)(wnd, msg, p1, p2);
  297.                 break;
  298.             case RIGHT_BUTTON:
  299.             case LEFT_BUTTON:
  300.             case DOUBLE_CLICK:
  301.             case BUTTON_RELEASED:
  302.                 /* --- don't send these messages unless the
  303.                     window is visible or has captured the mouse -- */
  304.                 if (isVisible(wnd) || wnd == CaptureMouse)
  305.                     rtn = (*wnd->wndproc)(wnd, msg, p1, p2);
  306.                 break;
  307.             case KEYBOARD:
  308.             case SHIFT_CHANGED:
  309.                 /* ------- don't send these messages unless the
  310.                     window is visible or has captured the keyboard -- */
  311.                 if (isVisible(wnd) || wnd == CaptureKeyboard)
  312.                     rtn = (*wnd->wndproc)(wnd, msg, p1, p2);
  313.                 break;
  314.             default:
  315.                 rtn = (*wnd->wndproc)(wnd, msg, p1, p2);
  316.                 break;
  317.         }
  318.     /* ----- window processor returned true or the message was sent
  319.         to no window at all (NULLWND) ----- */
  320.     if (rtn != FALSE)    {
  321.         /* --------- process messages that a window sends to the
  322.             system itself ---------- */
  323.         switch (msg)    {
  324.             case STOP:
  325.                 if (oldtimer != NULL)    {
  326.                     setvect(TIMER, oldtimer);
  327.                     oldtimer = NULL;
  328.                 }
  329.                 if (oldkeyboard != NULL)    {
  330.                     setvect(KEYBOARDVECT, oldkeyboard);
  331.                     oldkeyboard = NULL;
  332.                 }
  333.                 restorevideo();
  334.                 break;
  335. #ifdef INCLUDE_CLOCK
  336.             /* ------- clock messages --------- */
  337.             case CAPTURE_CLOCK:
  338.                 Cwnd = wnd;
  339.                 set_timer(clocktimer, 0);
  340.                 break;
  341.             case RELEASE_CLOCK:
  342.                 Cwnd = NULLWND;
  343.                 disable_timer(clocktimer);
  344.                 break;
  345. #endif
  346.             /* -------- keyboard messages ------- */
  347.             case KEYBOARD_CURSOR:
  348.                 if (wnd == NULLWND)
  349.                     cursor((int)p1, (int)p2);
  350.                 else
  351.                     cursor(GetClientLeft(wnd)+(int)p1,
  352.                                 GetClientTop(wnd)+(int)p2);
  353.                 break;
  354.             case CAPTURE_KEYBOARD:
  355.                 if (p2)
  356.                     ((WINDOW)p2)->PrevKeyboard=CaptureKeyboard;
  357.                 else
  358.                     wnd->PrevKeyboard = CaptureKeyboard;
  359.                 CaptureKeyboard = wnd;
  360.                 NoChildCaptureKeyboard = (int)p1;
  361.                 break;
  362.             case RELEASE_KEYBOARD:
  363.                 if (CaptureKeyboard == wnd || (int)p1)
  364.                     CaptureKeyboard = wnd->PrevKeyboard;
  365.                 else    {
  366.                     WINDOW twnd = CaptureKeyboard;
  367.                     while (twnd != NULLWND)    {
  368.                         if (twnd->PrevKeyboard == wnd)    {
  369.                             twnd->PrevKeyboard = wnd->PrevKeyboard;
  370.                             break;
  371.                         }
  372.                         twnd = twnd->PrevKeyboard;
  373.                     }
  374.                 }
  375.                 wnd->PrevKeyboard = NULLWND;
  376.                 NoChildCaptureKeyboard = FALSE;
  377.                 break;
  378.             case CURRENT_KEYBOARD_CURSOR:
  379.                 curr_cursor(&x, &y);
  380.                 *(int*)p1 = x;
  381.                 *(int*)p2 = y;
  382.                 break;
  383.             case SAVE_CURSOR:
  384.                 savecursor();
  385.                 break;
  386.             case RESTORE_CURSOR:
  387.                 restorecursor();
  388.                 break;
  389.             case HIDE_CURSOR:
  390.                 normalcursor();
  391.                 hidecursor();
  392.                 break;
  393.             case SHOW_CURSOR:
  394.                 if (p1)
  395.                     set_cursor_type(0x0106);
  396.                 else
  397.                     set_cursor_type(0x0607);
  398.                 unhidecursor();
  399.                 break;
  400.             case WAITKEYBOARD:
  401.                 waitforkeyboard();
  402.                 break;
  403.             /* -------- mouse messages -------- */
  404.             case RESET_MOUSE:
  405.                 resetmouse();
  406.                 set_mousetravel(0, SCREENWIDTH-1, 0, SCREENHEIGHT-1);
  407.                 break;
  408.             case MOUSE_INSTALLED:
  409.                 rtn = mouse_installed();
  410.                 break;
  411.             case MOUSE_TRAVEL:    {
  412.                 RECT rc = *(RECT *)p1;
  413.                 set_mousetravel(rc.lf, rc.rt, rc.tp, rc.bt);
  414.                 break;
  415.             }
  416.             case SHOW_MOUSE:
  417.                 show_mousecursor();
  418.                 break;
  419.             case HIDE_MOUSE:
  420.                 hide_mousecursor();
  421.                 break;
  422.             case MOUSE_CURSOR:
  423.                 set_mouseposition((int)p1, (int)p2);
  424.                 break;
  425.             case CURRENT_MOUSE_CURSOR:
  426.                 get_mouseposition((int*)p1,(int*)p2);
  427.                 break;
  428.             case WAITMOUSE:
  429.                 waitformouse();
  430.                 break;
  431.             case TESTMOUSE:
  432.                 rtn = mousebuttons();
  433.                 break;
  434.             case CAPTURE_MOUSE:
  435.                 if (p2)
  436.                     ((WINDOW)p2)->PrevMouse = CaptureMouse;
  437.                 else
  438.                     wnd->PrevMouse = CaptureMouse;
  439.                 CaptureMouse = wnd;
  440.                 NoChildCaptureMouse = (int)p1;
  441.                 break;
  442.             case RELEASE_MOUSE:
  443.                 if (CaptureMouse == wnd || (int)p1)
  444.                     CaptureMouse = wnd->PrevMouse;
  445.                 else    {
  446.                     WINDOW twnd = CaptureMouse;
  447.                     while (twnd != NULLWND)    {
  448.                         if (twnd->PrevMouse == wnd)    {
  449.                             twnd->PrevMouse = wnd->PrevMouse;
  450.                             break;
  451.                         }
  452.                         twnd = twnd->PrevMouse;
  453.                     }
  454.                 }
  455.                 wnd->PrevMouse = NULLWND;
  456.                 NoChildCaptureMouse = FALSE;
  457.                 break;
  458.             default:
  459.                 break;
  460.         }
  461.     }
  462.     return rtn;
  463. }
  464.  
  465. /* ---- dispatch messages to the message proc function ---- */
  466. int dispatch_message(void)
  467. {
  468.     WINDOW Mwnd, Kwnd;
  469.     /* -------- collect mouse and keyboard events ------- */
  470.     collect_events();
  471.     /* --------- dequeue and process events -------- */
  472.     while (EventQueueCtr > 0)  {
  473.         struct events ev;
  474.             
  475.         ev = EventQueue[EventQueueOffCtr];
  476.         if (++EventQueueOffCtr == MAXMESSAGES)
  477.             EventQueueOffCtr = 0;
  478.         --EventQueueCtr;
  479.  
  480.         /* ------ get the window in which a
  481.                         mouse event occurred ------ */
  482.         Mwnd = inWindow(ev.mx, ev.my);
  483.  
  484.         /* ---- process mouse captures ----- */
  485.         if (CaptureMouse != NULLWND)
  486.             if (Mwnd == NULLWND ||
  487.                     NoChildCaptureMouse ||
  488.                         GetParent(Mwnd) != CaptureMouse)
  489.                 Mwnd = CaptureMouse;
  490.  
  491.         /* ------ get the window in which a
  492.                         keyboard event occurred ------ */
  493.         Kwnd = inFocus;
  494.  
  495.         /* ---- process keyboard captures ----- */
  496.         if (CaptureKeyboard != NULLWND)
  497.             if (Kwnd == NULLWND ||
  498.                     NoChildCaptureKeyboard ||
  499.                         GetParent(Kwnd) != CaptureKeyboard)
  500.                 Kwnd = CaptureKeyboard;
  501.  
  502.         /* -------- send mouse and keyboard messages to the
  503.             window that should get them -------- */
  504.         switch (ev.event)    {
  505.             case SHIFT_CHANGED:
  506.             case KEYBOARD:
  507.                 SendMessage(Kwnd, ev.event, ev.mx, ev.my);
  508.                 break;
  509.             case LEFT_BUTTON:
  510.                 if (!CaptureMouse ||
  511.                         (!NoChildCaptureMouse &&
  512.                             GetParent(Mwnd) == CaptureMouse))
  513.                     if (Mwnd != inFocus)
  514.                         SendMessage(Mwnd, SETFOCUS, TRUE, 0);
  515.             case BUTTON_RELEASED:
  516.             case DOUBLE_CLICK:
  517.             case RIGHT_BUTTON:
  518.             case MOUSE_MOVED:
  519.                 SendMessage(Mwnd, ev.event, ev.mx, ev.my);
  520.                 break;
  521. #ifdef INCLUDE_CLOCK
  522.             case CLOCKTICK:
  523.                 SendMessage(Cwnd, ev.event,
  524.                     (PARAM) MK_FP(ev.mx, ev.my), 0);
  525.                 break;
  526. #endif
  527.             default:
  528.                 break;
  529.         }
  530.     }
  531.     /* ------ dequeue and process messages ----- */
  532.     while (MsgQueueCtr > 0)  {
  533.         struct msgs mq;
  534.  
  535.         mq = MsgQueue[MsgQueueOffCtr];
  536.         if (++MsgQueueOffCtr == MAXMESSAGES)
  537.             MsgQueueOffCtr = 0;
  538.         --MsgQueueCtr;
  539.         SendMessage(mq.wnd, mq.msg, mq.p1, mq.p2);
  540.         if (mq.msg == ENDDIALOG)
  541.             return FALSE;
  542.         if (mq.msg == STOP)    {
  543.             restorecursor();    
  544.             unhidecursor();
  545.             return FALSE;
  546.         }
  547.     }
  548.     return TRUE;
  549. }
  550.  
  551.